package cn.net.cfss.fgbp.face.console.controller;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import cn.net.cfss.fgbp.api.console.constant.DeleteFlagEnum;
import cn.net.cfss.fgbp.api.console.constant.IsLeafNodeEnum;
import cn.net.cfss.fgbp.api.console.constant.OrgTypeEnum;
import cn.net.cfss.fgbp.api.console.dto.SysUserDto;
import cn.net.cfss.fgbp.api.console.inte.ISysUserService;
import cn.net.cfss.fgbp.api.console.vo.SysUserVo;
import cn.net.cfss.fgbp.base.constant.ErrCodeEnum;
import cn.net.cfss.fgbp.base.except.CodeException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSONObject;
import cn.net.cfss.fgbp.api.console.dto.SysOrganDto;
import cn.net.cfss.fgbp.api.console.inte.ISysOrganService;
import cn.net.cfss.fgbp.api.console.vo.SysOrganVo;
import cn.net.cfss.fgbp.base.controller.BaseController;
import cn.net.cfss.fgbp.base.page.PageData;
import cn.net.cfss.fgbp.base.util.ReturnUtil;
import cn.net.cfss.fgbp.face.console.vo.BaseParas;
import io.swagger.annotations.ApiOperation;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@RestController
@RequestMapping("console/organ")
@Slf4j
public class SysOrganController extends BaseController {
	
    @Resource
    public ISysOrganService departmentService;
    @Autowired
    private ISysUserService sysUserService;

    @Value("${bsec.adminUserId:47282912709728697}")
    private String adminUserId;



    @ApiOperation("机构列表")
    @PostMapping("/pageData")
    public String list(@RequestBody BaseParas data) {
    	SysOrganVo search = JSONObject.toJavaObject(data.getPlain().getJSONObject("search"), SysOrganVo.class);
        PageData<SysOrganVo> pageData = PageData.createPagerData(data.getPlain().getIntValue("pageSize"),
                data.getPlain().getIntValue("pageNum"), search);
        pageData = departmentService.pageData(pageData);
        return ReturnUtil.returnSucc(pageData, pageData.getRows());
    }

    @ApiOperation("组织机构表树接口接口")
    @PostMapping("/tree")
    public String tree(@RequestBody BaseParas paras) {
        Long id = paras.getPlain().getLong("id");
        if (null == id || "".equals(id)){
            //查询一级列表
            return ReturnUtil.returnSucc(departmentService.listOne());
        }else {
            //查询下级列表
            SysOrganVo search = new SysOrganVo();
            search.setParentId(id);
            return ReturnUtil.returnSucc(departmentService.list(search));
        }
    }

    @ApiOperation("组织机构表树接口接口 根据用户权限")
    @PostMapping("/treeUser")
    public String treeUser(@RequestBody BaseParas paras) {
        Long id = paras.getPlain().getLong("id");
        Long userId = getUserId();
        if(null == userId || userId.toString().isEmpty()){
            return ReturnUtil.returnErr("获取用户Id失败，请重新登录！");
        }
        if(adminUserId.equals(userId.toString())){
            log.info("管理员账号登陆！");
            if (null == id || id.toString().isEmpty()){
                //查询一级列表
                return ReturnUtil.returnSucc(departmentService.listOne());
            }else {
                //查询下级列表
                SysOrganVo search = new SysOrganVo();
                search.setParentId(id);
                return ReturnUtil.returnSucc(departmentService.list(search));
            }
        }
        //获取用户关联机构  默认为都是内部员工
        SysUserVo sysUserVo = sysUserService.get(userId);
        Long organId = sysUserVo.getServiceProvider();
        //外部用户
        if(!cn.net.cfss.fgbp.api.console.constant.YesOrNoEnum.YES.equals(sysUserVo.getIsInternalStaff())){
            List<Long> nullList = new ArrayList<>();
            return ReturnUtil.returnSucc(nullList);
        }
        //查询机构下级ID集合
        List<Long> organIds = departmentService.getIds(organId);
        log.info("查询机构下级ID集合",organIds);
        if(organIds.isEmpty()){
            log.error("查询机构下级ID集合错误！");
            return ReturnUtil.returnSucc(organIds);
        }

        if (null == id || id.toString().isEmpty()){
            //查询一级列表
            List<SysOrganVo> sysOrganVoList = departmentService.listOne();
            //判断是否是该用户所属机构的下级机构  拼接是否可选标识
            for (SysOrganVo sysOrganVo : sysOrganVoList){
                if(organIds.contains(sysOrganVo.getId())){
                    sysOrganVo.setPermission(false);
                    continue;
                }
                sysOrganVo.setPermission(true);
            }
            return ReturnUtil.returnSucc(sysOrganVoList);
        }else {
            //查询下级列表
            SysOrganVo search = new SysOrganVo();
            search.setParentId(id);
            List<SysOrganVo> sysOrganVoList = departmentService.list(search);
            //判断是否是该用户所属机构的下级机构 拼接是否可选标识
            for (SysOrganVo sysOrganVo : sysOrganVoList){
                if(organIds.contains(sysOrganVo.getId())){
                    sysOrganVo.setPermission(false);
                    continue;
                }
                sysOrganVo.setPermission(true);
            }
            return ReturnUtil.returnSucc(sysOrganVoList);
        }
    }

    @ApiOperation("组织机构表树一级列表分页查询")
    @PostMapping("/treeOne")
    public String treeOne(@RequestBody BaseParas data){
        SysOrganVo search = new SysOrganVo();
        PageData<SysOrganVo> pageData = PageData.createPagerData(data.getPlain().getIntValue("pageSize"),
                data.getPlain().getIntValue("pageNum"), search);
        pageData = departmentService.pageOne(pageData);
        return ReturnUtil.returnSucc(pageData, pageData.getRows());
    }

    /**
     * 查询父级id集合
     * @param paras
     * @return
     */
    @ApiOperation("查询父级id集合")
    @PostMapping("/queyParentIds")
    public String queyParentIds(@RequestBody BaseParas paras) {
        Long id = paras.getPlain().getLong("id");
        if (null == id || "".equals(id)){
            return ReturnUtil.returnErr("id不可为空");
        }
        SysOrganVo sysOrganVo = new SysOrganVo();
        List<String> ids = new ArrayList<>();

        sysOrganVo = departmentService.detail(id);
        if(null == sysOrganVo || DeleteFlagEnum.DEL.equals(sysOrganVo.getDeleteFlag())){
            log.error("关联机构被删除请重新关联,id:{}",id);
            return ReturnUtil.returnErr("关联机构被删除请重新关联！");
        }
        ids.add(String.valueOf(sysOrganVo.getId()));
        //查询父级ID添加集合
        while (null != sysOrganVo.getParentId()){
            sysOrganVo = departmentService.detail(sysOrganVo.getParentId());
            if(null == sysOrganVo || DeleteFlagEnum.DEL.equals(sysOrganVo.getDeleteFlag())){
                log.error("关联机构被删除请重新关联,id:{}",id);
                return ReturnUtil.returnErr("关联机构被删除请重新关联！");
            }
            ids.add(String.valueOf(sysOrganVo.getId()));
        }
        //倒序集合  按级别排序
        Collections.reverse(ids);

        return ReturnUtil.returnSucc(ids);
    }

    @ApiOperation("机构添加")
    @PostMapping("/add")
    public String add(@RequestBody BaseParas paras) {
    	SysOrganDto dto = JSONObject.toJavaObject(paras.getPlain(), SysOrganDto.class);

        //判断名称是否重复
        boolean flag = departmentService.checkAddOrganName(dto.getName());
        if(flag){
            log.error("新增名称重复,名称:{}",dto.getName());
            return ReturnUtil.returnErr("新增名称重复，请重新输入");
        }
        //校验关联父级是否正确
        if(!this.checkParentLeve(dto)){
            log.error("关联父级错误！机构新增对象：{}",dto.toString());
            return ReturnUtil.returnErr("关联父级错误！请重新关联");
        }


        Long dtoParentId = dto.getParentId();
    	if(null != dtoParentId && !"".equals(dtoParentId)){
            SysOrganVo dtoParent = departmentService.detail(dtoParentId);
            dto.setParentName(dtoParent.getName());
        }
        //新增
    	dto.setCreateBy(getUserName());
        dto.setIsLeafNode(IsLeafNodeEnum.IS_LEAF_NODE);
        departmentService.save(dto);
        return ReturnUtil.returnSucc();
    }

    @ApiOperation("机构删除")
    @PostMapping("/del")
    @Transactional
    public String delete(@RequestBody BaseParas paras) {
        Long id = paras.getPlain().getLong("id");
        SysUserVo sysUserVo = new SysUserVo();
        sysUserVo.setServiceProvider(id);
        List<SysUserDto> sysUserDtoList = sysUserService.queryList(sysUserVo);
        if(!sysUserDtoList.isEmpty()){
            log.error("该机构已经关联用户，不可删除！机构名称：{}，机构Id：{}",sysUserDtoList.get(0).getServiceProviderName(),id);
            return ReturnUtil.returnErr("该机构已经关联用户，不可删除！");
        }
        //查询是否关联任务
       /* TaskDtoVo searchc = new TaskDtoVo();
        searchc.setOrganId(id);
        searchc.setDeleteFlag(cn.net.cfss.fgbp.api.bsec.constant.DeleteFlagEnum.NOT_DEL);
        List<TaskDtoVo> taskDtoVoList = taskService.list(searchc);
        log.info("查询是否关联任务,机构ID：{}",id);
        if(null != taskDtoVoList && taskDtoVoList.size()>0){
            log.error("该机构已经关联任务,机构ID：{}",id);
            return ReturnUtil.returnErr("该机构已经关联任务，不可删除！");
        }*/

        SysOrganVo sysOrganVo = departmentService.detail(id);
        if(null == sysOrganVo){
            log.error("数据错误！机构Id：{}",id);
            return ReturnUtil.returnErr("数据错误！");
        }
        if(IsLeafNodeEnum.NOT_LEAF_NODE.equals(sysOrganVo.getIsLeafNode())){
            log.error("该机构存在子节点，不可删除！机构：{}",sysOrganVo);
            return ReturnUtil.returnErr("该机构存在子节点，不可删除！");
        }
        sysOrganVo.setDeleteFlag(DeleteFlagEnum.DEL);
        departmentService.updateParentIsLeafNode(sysOrganVo.getId());
    	departmentService.update(sysOrganVo);
        return ReturnUtil.returnSucc();
    }

    @ApiOperation("机构修改")
    @PostMapping("/update")
    public String update(@RequestBody BaseParas paras) {
    	SysOrganDto dto = JSONObject.toJavaObject(paras.getPlain(), SysOrganDto.class);
    	dto.setUpdateBy(getUserName());
    	//判断名称是否重复
        boolean flag = departmentService.checkUpdateOrganName(dto.getName(),dto.getId());
        if(flag){
            log.error("修改名称重复,名称:{}",dto.getName());
            return ReturnUtil.returnErr("修改名称重复，请重新输入");
        }
        //校验关联父级是否正确
        if(!this.checkParentLeve(dto)){
            log.error("关联父级错误！机构新增对象：{}",dto.toString());
            return ReturnUtil.returnErr("关联父级错误！请重新关联");
        }
        //不能选择自己作为自己的父级
        if (OrgTypeEnum.GATHER_ORG.equals(dto.getOrganType()) && dto.getParentId() != null) {
            //类型为总公司时，不能有父级机构
            return ReturnUtil.returnErr("关联父级错误！请重新关联");
        }
        if (dto.getParentId() != null && dto.getParentId().equals(dto.getId())) {
            //不能选择自己作为自己的父机构
            return ReturnUtil.returnErr("关联父级错误！请重新关联");
        }

    	departmentService.update(dto);
        return ReturnUtil.returnSucc();
    }

    @ApiOperation("机构详情")
    @PostMapping("/detail/{id}")
    public String detail(@PathVariable Long id) {
        return ReturnUtil.returnSucc(departmentService.detail(id));
    }

    /**
     * 校验关联父级是否正确
     * @param dto
     * @return
     */
    public boolean checkParentLeve(SysOrganDto dto){
        if(null == dto){
            return false;
        }
        Long parentId = dto.getParentId();
        //父级为空 为总公司
        if(null == parentId){
            if(OrgTypeEnum.GATHER_ORG.equals(dto.getOrganType())){
                return true;
            } else {
                //如果父级为空时，不是总公司，异常
                return  false;
            }
        }
        //父级机构
        SysOrganVo parentVo = departmentService.detail(dto.getParentId());
        //如果创建省公司  关联为总公司
        if (OrgTypeEnum.BRANCH_ORG.equals(dto.getOrganType())){
            if(OrgTypeEnum.GATHER_ORG.equals(parentVo.getOrganType())){
                return true;
            }
        }

        //如果创建市公司  关联为省公司
        if (OrgTypeEnum.SUB_ORG.equals(dto.getOrganType())){
            if(OrgTypeEnum.BRANCH_ORG.equals(parentVo.getOrganType())){
                return true;
            }
        }
        return false;
    }

}
